AtklÄjiet WebCodecs jaudu! VisaptveroÅ”s ceļvedis video kadru datu piekļuvei un manipulÄcijai, izmantojot VideoFrame plaknes. Uzziniet par pikseļu formÄtiem, atmiÅas izkÄrtojumu un progresÄ«vu video apstrÄdi pÄrlÅ«kÄ.
WebCodecs VideoFrame plakne: padziļinÄta izpÄte par piekļuvi video kadru datiem
WebCodecs ir paradigmas maiÅa tÄ«mekļa mediju apstrÄdÄ. Tas nodroÅ”ina zema lÄ«meÅa piekļuvi mediju pamatelementiem, ļaujot izstrÄdÄtÄjiem veidot sarežģītas lietojumprogrammas tieÅ”i pÄrlÅ«kprogrammÄ. Viena no jaudÄ«gÄkajÄm WebCodecs funkcijÄm ir VideoFrame objekts un tÄ ietvaros esoÅ”Äs VideoFrame plaknes, kas atklÄj video kadru neapstrÄdÄtos pikseļu datus. Å is raksts sniedz visaptveroÅ”u ceļvedi VideoFrame plakÅu izpratnei un izmantoÅ”anai progresÄ«vai video manipulÄcijai.
Izpratne par VideoFrame objektu
Pirms iedziļinÄmies plaknÄs, Ä«sumÄ apskatÄ«sim paÅ”u VideoFrame objektu. VideoFrame pÄrstÄv vienu video kadru. Tas ietver dekodÄtus (vai kodÄtus) video datus, kÄ arÄ« saistÄ«tos metadatus, piemÄram, laika zÄ«mogu, ilgumu un formÄta informÄciju. VideoFrame API piedÄvÄ metodes, lai:
- Nolasītu pikseļu datus: Šeit tiek izmantotas plaknes.
- KopÄtu kadrus: Izveidotu jaunus
VideoFrameobjektus no jau esoÅ”iem. - AizvÄrtu kadrus: AtbrÄ«votu pamatÄ esoÅ”os resursus, ko aizÅem kadrs.
VideoFrame objekts tiek izveidots dekodÄÅ”anas procesÄ, parasti ar VideoDecoder, vai manuÄli, veidojot pielÄgotu kadru.
Kas ir VideoFrame plaknes?
VideoFrame pikseļu dati bieži tiek organizÄti vairÄkÄs plaknÄs, Ä«paÅ”i tÄdos formÄtos kÄ YUV. Katra plakne pÄrstÄv atŔķirÄ«gu attÄla komponentu. PiemÄram, YUV420 formÄtÄ ir trÄ«s plaknes:
- Y (Luma): PÄrstÄv attÄla spilgtumu (luminiscenci). Å Ä« plakne satur pelÄktoÅu informÄciju.
- U (Cb): PÄrstÄv zilo krÄsu atŔķirÄ«bas hroma komponentu.
- V (Cr): PÄrstÄv sarkano krÄsu atŔķirÄ«bas hroma komponentu.
RGB formÄti, lai arÄ« Ŕķietami vienkÄrÅ”Äki, dažos gadÄ«jumos var arÄ« izmantot vairÄkas plaknes. PlakÅu skaits un to nozÄ«me ir pilnÄ«bÄ atkarÄ«ga no VideoFrame VideoPixelFormat.
PlakÅu izmantoÅ”anas priekÅ”rocÄ«ba ir tÄ, ka tÄ Ä¼auj efektÄ«vi piekļūt un manipulÄt ar specifiskiem krÄsu komponentiem. PiemÄram, jÅ«s varÄtu vÄlÄties pielÄgot tikai spilgtumu (Y plakni), neietekmÄjot krÄsu (U un V plaknes).
Piekļuve VideoFrame plaknÄm: API
VideoFrame API nodroÅ”ina Å”Ädas metodes, lai piekļūtu plakÅu datiem:
copyTo(destination, options): KopÄVideoFramesaturu uz galamÄrÄ·i, kas var bÅ«t citsVideoFrame,CanvasImageBitmapvaiArrayBufferView.optionsobjekts kontrolÄ, kuras plaknes tiek kopÄtas un kÄ. Å is ir galvenais mehÄnisms piekļuvei plaknÄm.
options objekts copyTo metodÄ Ä¼auj norÄdÄ«t video kadra datu izkÄrtojumu un mÄrÄ·i. GalvenÄs Ä«paŔības ietver:
format: VÄlamais kopÄto datu pikseļu formÄts. Tas var bÅ«t tÄds pats kÄ oriÄ£inÄlajamVideoFramevai cits formÄts (piemÄram, konvertÄjot no YUV uz RGB).codedWidthuncodedHeight: Video kadra platums un augstums pikseļos.layout: Objektu masÄ«vs, kas apraksta katras plaknes izkÄrtojumu atmiÅÄ. Katrs objekts masÄ«vÄ norÄda:offset: NobÄ«de baitos no datu bufera sÄkuma lÄ«dz plaknes datu sÄkumam.stride: Baitu skaits starp katras rindas sÄkumu plaknÄ. Tas ir bÅ«tiski, lai apstrÄdÄtu papildinÄjumu (padding).
ApskatÄ«sim piemÄru, kÄ kopÄt YUV420 VideoFrame neapstrÄdÄtÄ buferÄ«:
async function copyYUV420ToBuffer(videoFrame, buffer) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
// YUV420 ir 3 plaknes: Y, U un V
const yPlaneSize = width * height;
const uvPlaneSize = width * height / 4;
const layout = [
{ offset: 0, stride: width }, // Y plakne
{ offset: yPlaneSize, stride: width / 2 }, // U plakne
{ offset: yPlaneSize + uvPlaneSize, stride: width / 2 } // V plakne
];
await videoFrame.copyTo(buffer, {
format: 'I420',
codedWidth: width,
codedHeight: height,
layout: layout
});
videoFrame.close(); // Svarīgi atbrīvot resursus
}
Paskaidrojums:
- MÄs aprÄÄ·inÄm katras plaknes izmÄru, pamatojoties uz
widthunheight. Y ir pilnÄ izŔķirtspÄjÄ, kamÄr U un V ir ar samazinÄtu iztverÅ”anu (4:2:0). layoutmasÄ«vs definÄ atmiÅas izkÄrtojumu.offsetnorÄda, kur katra plakne sÄkas buferÄ«, unstridenorÄda baitu skaitu, kas jÄpÄrlec, lai nokļūtu lÄ«dz nÄkamajai rindai Å”ajÄ plaknÄ.formatopcija ir iestatÄ«ta uz 'I420', kas ir izplatÄ«ts YUV420 formÄts.- BÅ«tiski, ka pÄc kopÄÅ”anas tiek izsaukts
videoFrame.close(), lai atbrīvotu resursus.
Pikseļu formÄti: IespÄju pasaule
Pikseļu formÄtu izpratne ir bÅ«tiska, strÄdÄjot ar VideoFrame plaknÄm. VideoPixelFormat definÄ, kÄ krÄsu informÄcija tiek kodÄta video kadrÄ. Å eit ir daži izplatÄ«ti pikseļu formÄti, ar kuriem jÅ«s varÄtu saskarties:
- I420 (YUV420p): PlanÄrs YUV formÄts, kur Y, U un V komponenti tiek glabÄti atseviŔķÄs plaknÄs. U un V iztverÅ”ana ir samazinÄta 2 reizes gan horizontÄlajÄ, gan vertikÄlajÄ dimensijÄ. Tas ir ļoti izplatÄ«ts un efektÄ«vs formÄts.
- NV12 (YUV420sp): DaļÄji planÄrs YUV formÄts, kur Y tiek glabÄts vienÄ plaknÄ, un U un V komponenti ir savstarpÄji savietoti otrÄ plaknÄ.
- RGBA: SarkanÄ, zaļÄ, zilÄ un alfa komponenti tiek glabÄti vienÄ plaknÄ, parasti ar 8 bitiem katram komponentam (32 biti uz pikseli). Komponentu secÄ«ba var atŔķirties (piemÄram, BGRA).
- RGB565: SarkanÄ, zaÄ¼Ä un zilÄ komponenti tiek glabÄti vienÄ plaknÄ ar 5 bitiem sarkanajam, 6 bitiem zaļajam un 5 bitiem zilajam (16 biti uz pikseli).
- GRAYSCALE: PÄrstÄv pelÄktoÅu attÄlus ar vienu luma (spilgtuma) vÄrtÄ«bu katram pikselim.
VideoFrame.format Ä«paŔība jums pateiks konkrÄtÄ kadra pikseļu formÄtu. Noteikti pÄrbaudiet Å”o Ä«paŔību, pirms mÄÄ£inÄt piekļūt plaknÄm. JÅ«s varat iepazÄ«ties ar WebCodecs specifikÄciju, lai iegÅ«tu pilnu atbalstÄ«to formÄtu sarakstu.
Praktiski pielietojuma piemÄri
Piekļuve VideoFrame plaknÄm paver plaÅ”as iespÄjas progresÄ«vai video apstrÄdei pÄrlÅ«kprogrammÄ. Å eit ir daži piemÄri:
1. ReÄllaika video efekti
JÅ«s varat lietot reÄllaika video efektus, manipulÄjot ar pikseļu datiem VideoFrame. PiemÄram, jÅ«s varÄtu ieviest pelÄktoÅu filtru, aprÄÄ·inot vidÄjo R, G un B komponentu vÄrtÄ«bu katram pikselim RGBA kadrÄ un pÄc tam iestatot visus trÄ«s komponentus uz Å”o vidÄjo vÄrtÄ«bu. JÅ«s varÄtu arÄ« izveidot sÄpijas toÅa efektu vai pielÄgot spilgtumu un kontrastu.
async function applyGrayscale(videoFrame) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
const buffer = new ArrayBuffer(width * height * 4); // RGBA
const rgba = new Uint8ClampedArray(buffer);
await videoFrame.copyTo(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height
});
for (let i = 0; i < rgba.length; i += 4) {
const r = rgba[i];
const g = rgba[i + 1];
const b = rgba[i + 2];
const gray = (r + g + b) / 3;
rgba[i] = gray; // Sarkanais
rgba[i + 1] = gray; // Zaļais
rgba[i + 2] = gray; // Zilais
}
// Izveido jaunu VideoFrame no modificÄtajiem datiem.
const newFrame = new VideoFrame(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
videoFrame.close(); // AtbrÄ«vo oriÄ£inÄlo kadru
return newFrame;
}
2. Datorredzes lietojumprogrammas
VideoFrame plaknes nodroÅ”ina tieÅ”u piekļuvi pikseļu datiem, kas nepiecieÅ”ami datorredzes uzdevumiem. JÅ«s varat izmantot Å”os datus, lai ieviestu algoritmus objektu noteikÅ”anai, sejas atpazīŔanai, kustÄ«bas izsekoÅ”anai un citur. JÅ«s varat izmantot WebAssembly veiktspÄjas kritiskÄm koda daļÄm.
PiemÄram, jÅ«s varÄtu konvertÄt krÄsainu VideoFrame uz pelÄktoÅiem un pÄc tam pielietot malu noteikÅ”anas algoritmu (piemÄram, Sobel operatoru), lai identificÄtu malas attÄlÄ. To varÄtu izmantot kÄ priekÅ”apstrÄdes soli objektu atpazīŔanai.
3. Video rediÄ£ÄÅ”ana un kompozÄ«cija
JÅ«s varat izmantot VideoFrame plaknes, lai ieviestu video rediÄ£ÄÅ”anas funkcijas, piemÄram, apgrieÅ”anu, mÄrogoÅ”anu, rotÄciju un kompozÄ«ciju. TieÅ”i manipulÄjot ar pikseļu datiem, jÅ«s varat izveidot pielÄgotas pÄrejas un efektus.
PiemÄram, jÅ«s varÄtu apgriezt VideoFrame, kopÄjot tikai daļu no pikseļu datiem uz jaunu VideoFrame. Jums bÅ«tu attiecÄ«gi jÄpielÄgo layout nobÄ«des un soļi.
4. PielÄgoti kodeki un pÄrkodÄÅ”ana
Lai gan WebCodecs nodroÅ”ina iebÅ«vÄtu atbalstu izplatÄ«tiem kodekiem, piemÄram, AV1, VP9 un H.264, jÅ«s to varat izmantot arÄ«, lai ieviestu pielÄgotus kodekus vai pÄrkodÄÅ”anas konveijerus. Jums bÅ«tu paÅ”iem jÄapstrÄdÄ kodÄÅ”anas un dekodÄÅ”anas process, bet VideoFrame plaknes ļauj piekļūt un manipulÄt ar neapstrÄdÄtiem pikseļu datiem. Tas varÄtu bÅ«t noderÄ«gi niÅ”as video formÄtiem vai specializÄtÄm kodÄÅ”anas prasÄ«bÄm.
5. Progresīva analītika
Piekļūstot pamatÄ esoÅ”ajiem pikseļu datiem, jÅ«s varat veikt dziļu video satura analÄ«zi. Tas ietver tÄdus uzdevumus kÄ ainas vidÄjÄ spilgtuma mÄrīŔana, dominÄjoÅ”o krÄsu identificÄÅ”ana vai izmaiÅu noteikÅ”ana ainas saturÄ. Tas var nodroÅ”inÄt progresÄ«vas video analÄ«tikas lietojumprogrammas droŔībai, novÄroÅ”anai vai satura analÄ«zei.
Darbs ar Canvas un WebGL
Lai gan jÅ«s varat tieÅ”i manipulÄt ar pikseļu datiem VideoFrame plaknÄs, bieži vien rezultÄts ir jÄattÄlo uz ekrÄna. CanvasImageBitmap saskarne nodroÅ”ina tiltu starp VideoFrame un <canvas> elementu. JÅ«s varat izveidot CanvasImageBitmap no VideoFrame un pÄc tam to uzzÄ«mÄt uz audekla, izmantojot drawImage() metodi.
async function renderVideoFrameToCanvas(videoFrame, canvas) {
const bitmap = await createImageBitmap(videoFrame);
const ctx = canvas.getContext('2d');
ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close(); // Atbrīvo bitmap resursus
videoFrame.close(); // Atbrīvo VideoFrame resursus
}
Lai veiktu progresÄ«vÄku renderÄÅ”anu, varat izmantot WebGL. JÅ«s varat augÅ”upielÄdÄt pikseļu datus no VideoFrame plaknÄm WebGL tekstÅ«rÄs un pÄc tam izmantot ÄnotÄjus (shaders), lai lietotu efektus un transformÄcijas. Tas ļauj jums izmantot GPU augstas veiktspÄjas video apstrÄdei.
VeiktspÄjas apsvÄrumi
Darbs ar neapstrÄdÄtiem pikseļu datiem var bÅ«t skaitļoÅ”anas ziÅÄ intensÄ«vs, tÄpÄc ir svarÄ«gi apsvÄrt veiktspÄjas optimizÄciju. Å eit ir daži padomi:
- MinimizÄjiet kopÄÅ”anu: Izvairieties no nevajadzÄ«gas pikseļu datu kopÄÅ”anas. MÄÄ£iniet veikt operÄcijas uz vietas, kad vien iespÄjams.
- Izmantojiet WebAssembly: VeiktspÄjas kritiskÄm koda daļÄm apsveriet iespÄju izmantot WebAssembly. WebAssembly var nodroÅ”inÄt gandrÄ«z dabiskai lÄ«dzÄ«gu veiktspÄju skaitļoÅ”anas ziÅÄ intensÄ«viem uzdevumiem.
- OptimizÄjiet atmiÅas izkÄrtojumu: IzvÄlieties savai lietojumprogrammai piemÄrotÄko pikseļu formÄtu un atmiÅas izkÄrtojumu. Apsveriet iespÄju izmantot saspiestos formÄtus (piemÄram, RGBA), ja jums nav nepiecieÅ”ams bieži piekļūt atseviŔķiem krÄsu komponentiem.
- Izmantojiet OffscreenCanvas: Fona apstrÄdei izmantojiet
OffscreenCanvas, lai izvairÄ«tos no galvenÄ pavediena bloÄ·ÄÅ”anas. - ProfilÄjiet savu kodu: Izmantojiet pÄrlÅ«kprogrammas izstrÄdÄtÄju rÄ«kus, lai profilÄtu savu kodu un identificÄtu veiktspÄjas vÄjÄs vietas.
PÄrlÅ«kprogrammu saderÄ«ba
WebCodecs un VideoFrame API tiek atbalstÄ«ti lielÄkajÄ daÄ¼Ä moderno pÄrlÅ«kprogrammu, tostarp Chrome, Firefox un Safari. TomÄr atbalsta lÄ«menis var atŔķirties atkarÄ«bÄ no pÄrlÅ«kprogrammas versijas un operÄtÄjsistÄmas. PÄrbaudiet jaunÄkÄs pÄrlÅ«kprogrammu saderÄ«bas tabulas tÄdÄs vietnÄs kÄ MDN Web Docs, lai pÄrliecinÄtos, ka jÅ«su izmantotÄs funkcijas tiek atbalstÄ«tas mÄrÄ·a pÄrlÅ«kprogrammÄs. Starp-pÄrlÅ«ku saderÄ«bai ieteicams izmantot funkciju noteikÅ”anu.
BiežÄkÄs kļūdas un problÄmu risinÄÅ”ana
Å eit ir dažas biežÄkÄs kļūdas, no kurÄm jÄizvairÄs, strÄdÄjot ar VideoFrame plaknÄm:
- Nepareizs izkÄrtojums: PÄrliecinieties, ka
layoutmasÄ«vs precÄ«zi apraksta pikseļu datu atmiÅas izkÄrtojumu. Nepareizas nobÄ«des vai soļi var novest pie bojÄtiem attÄliem. - NesakritÄ«gi pikseļu formÄti: PÄrliecinieties, ka pikseļu formÄts, ko norÄdÄt
copyTometodÄ, atbilst faktiskajamVideoFrameformÄtam. - AtmiÅas noplÅ«des: VienmÄr aizveriet
VideoFrameunCanvasImageBitmapobjektus, kad esat beidzis ar tiem darboties, lai atbrÄ«votu pamatÄ esoÅ”os resursus. To nedarot, var rasties atmiÅas noplÅ«des. - Asinhronas operÄcijas: Atcerieties, ka
copyToir asinhrona operÄcija. Izmantojietawait, lai nodroÅ”inÄtu, ka kopÄÅ”anas operÄcija tiek pabeigta, pirms piekļūstat pikseļu datiem. - DroŔības ierobežojumi: Esiet informÄti par droŔības ierobežojumiem, kas var attiekties, piekļūstot pikseļu datiem no citu domÄnu video.
PiemÄrs: YUV uz RGB konvertÄcija
ApskatÄ«sim sarežģītÄku piemÄru: YUV420 VideoFrame konvertÄÅ”anu uz RGB VideoFrame. Tas ietver Y, U un V plakÅu nolasīŔanu, to konvertÄÅ”anu uz RGB vÄrtÄ«bÄm un pÄc tam jauna RGB VideoFrame izveidi.
Å o konvertÄciju var ieviest, izmantojot Å”Ädu formulu:
R = Y + 1.402 * (Cr - 128)
G = Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)
B = Y + 1.772 * (Cb - 128)
Å eit ir kods:
async function convertYUV420ToRGBA(videoFrame) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
const yPlaneSize = width * height;
const uvPlaneSize = width * height / 4;
const yuvBuffer = new ArrayBuffer(yPlaneSize + 2 * uvPlaneSize);
const yuvPlanes = new Uint8ClampedArray(yuvBuffer);
const layout = [
{ offset: 0, stride: width }, // Y plakne
{ offset: yPlaneSize, stride: width / 2 }, // U plakne
{ offset: yPlaneSize + uvPlaneSize, stride: width / 2 } // V plakne
];
await videoFrame.copyTo(yuvPlanes, {
format: 'I420',
codedWidth: width,
codedHeight: height,
layout: layout
});
const rgbaBuffer = new ArrayBuffer(width * height * 4);
const rgba = new Uint8ClampedArray(rgbaBuffer);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const yIndex = y * width + x;
const uIndex = Math.floor(y / 2) * (width / 2) + Math.floor(x / 2) + yPlaneSize;
const vIndex = Math.floor(y / 2) * (width / 2) + Math.floor(x / 2) + yPlaneSize + uvPlaneSize;
const Y = yuvPlanes[yIndex];
const U = yuvPlanes[uIndex] - 128;
const V = yuvPlanes[vIndex] - 128;
let R = Y + 1.402 * V;
let G = Y - 0.34414 * U - 0.71414 * V;
let B = Y + 1.772 * U;
R = Math.max(0, Math.min(255, R));
G = Math.max(0, Math.min(255, G));
B = Math.max(0, Math.min(255, B));
const rgbaIndex = y * width * 4 + x * 4;
rgba[rgbaIndex] = R;
rgba[rgbaIndex + 1] = G;
rgba[rgbaIndex + 2] = B;
rgba[rgbaIndex + 3] = 255; // Alfa
}
}
const newFrame = new VideoFrame(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
videoFrame.close(); // AtbrÄ«vo oriÄ£inÄlo kadru
return newFrame;
}
Å is piemÄrs demonstrÄ spÄku un sarežģītÄ«bu, strÄdÄjot ar VideoFrame plaknÄm. Tas prasa labu izpratni par pikseļu formÄtiem, atmiÅas izkÄrtojumu un krÄsu telpu konvertÄcijÄm.
NoslÄgums
VideoFrame plaknes API WebCodecs atver jaunu kontroles lÄ«meni pÄr video apstrÄdi pÄrlÅ«kprogrammÄ. Izprotot, kÄ piekļūt un tieÅ”i manipulÄt ar pikseļu datiem, jÅ«s varat izveidot progresÄ«vas lietojumprogrammas reÄllaika video efektiem, datorredzei, video rediÄ£ÄÅ”anai un citur. Lai gan darbs ar VideoFrame plaknÄm var bÅ«t sarežģīts, potenciÄlais ieguvums ir ievÄrojams. WebCodecs turpinot attÄ«stÄ«ties, tas neapÅ”aubÄmi kļūs par bÅ«tisku rÄ«ku tÄ«mekļa izstrÄdÄtÄjiem, kas strÄdÄ ar medijiem.
MÄs aicinÄm jÅ«s eksperimentÄt ar VideoFrame plaknes API un izpÄtÄ«t tÄs iespÄjas. Izprotot pamatprincipus un pielietojot labÄkÄs prakses, jÅ«s varat izveidot inovatÄ«vas un veiktspÄjÄ«gas video lietojumprogrammas, kas paplaÅ”ina iespÄjamÄ robežas pÄrlÅ«kprogrammÄ.
Papildu mÄcÄ«bu materiÄli
- MDN Web Docs par WebCodecs
- WebCodecs specifikÄcija
- WebCodecs paraugkodu repozitoriji GitHub.